package com.glsc.ngateway.oaflow.service.xirtrade;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Pair;
import com.glsc.ngateway.common.base.domain.mysql.gateway.oaflow.xirtrade.TOaFlowXirTradeInfo;
import com.glsc.ngateway.common.api.oaflow.dto.xirtrade.TOaFlowXirTradeConfigDto;
import com.glsc.ngateway.common.api.oaflow.dto.xirtrade.TOaFlowXirTradeConfigSearchParamDto;
import com.glsc.ngateway.common.api.oaflow.dto.xirtrade.TOaFlowXirTradeInfoGSBDto;
import com.glsc.ngateway.common.base.enums.OaFlowXirTradeInfoStatusEnum;
import com.glsc.ngateway.common.base.repo.mysql.gateway.oaflow.TOaFlowXirTradeInfoRepository;
import com.glsc.ngateway.common.xir.domain.*;
import com.glsc.ngateway.common.xir.repo.*;
import com.glsc.ngateway.oaflow.exception.OaflowException;
import com.glsc.ngateway.oaflow.service.xirtrade.enums.XirTradeOaFlowTypeEnum;
import com.glsc.ngateway.oaflow.service.xirtrade.enums.XirTtrdOtcTradeOrdStatusEnum;
import com.glsc.ngateway.oaflow.service.xirtrade.enums.衡泰业务类型枚举_固收部;
import lombok.*;
import lombok.experimental.SuperBuilder;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
public class XirTradeGSBFactory extends AbstractXirTradeFactory {

    private static Logger logger = LoggerFactory.getLogger(TOaFlowXirTradeService.class);
    private static TbndRepository tbndRepo;
    private static TtrdSetInstructionRepository instructionRepo;
    private static TtrdSetInstructionSecuRepository instructionSecuRepo;
    private static VtrdOtcTradeAllRepository vtrdOtcTradeAllRepo;
    private static TtrdOtcTradeRepository otcTradeRepo;
    private static TOaFlowXirTradeInfoRepository xirTradeInfoRepo;
    private static TtrdOtcCounterpartyBankRepository counterpartyBankRepo;
    private static TOaFlowXirTradeService xirTradeService;

    @Override
    public String getType() {
        return "固收部";
    }

    /**
     * 配方表Map<衡泰业务类别，生产步骤>
     * 一般为查找需要同步的数据->查询相关数据->生成同步数据
     * TODO:为减少连接查询衡泰数据库次数，去掉配方表，将所有业务类型做聚合，按统一逻辑处理
     */
    private static final Map<衡泰业务类型枚举_固收部, List<Function<BuildContext, Boolean>>> FORMULA_MAP = new HashMap<>() {{
        put(衡泰业务类型枚举_固收部.债券认购_分销买入_首期, List.of(
                XirTradeGSBFactory::buildTrade,
                XirTradeGSBFactory::buildAndFilterTbnd,
                XirTradeGSBFactory::fiterSynced,
                XirTradeGSBFactory::buildParty,
                XirTradeGSBFactory::fit
        ));
        put(衡泰业务类型枚举_固收部.债券借贷_定期付息, List.of(
                XirTradeGSBFactory::buildInst,
                XirTradeGSBFactory::buildTrade,
                XirTradeGSBFactory::buildAndFilterTbnd,
                XirTradeGSBFactory::fiterSynced,
                XirTradeGSBFactory::buildParty,
                XirTradeGSBFactory::fit
        ));
        put(衡泰业务类型枚举_固收部.债券借贷_到期, List.of(
                XirTradeGSBFactory::buildInst,
                XirTradeGSBFactory::buildTrade,
                XirTradeGSBFactory::buildAndFilterTbnd,
                XirTradeGSBFactory::fiterSynced,
                XirTradeGSBFactory::buildParty,
                XirTradeGSBFactory::buildSecu,
                XirTradeGSBFactory::fit
        ));
    }};

    /**
     * 根据日期查询所有已配置的类别，生成同步过的数据
     * 【重要】为防止并发，只能串行化执行，使用悲观锁
     */
    @Override
    public List<TOaFlowXirTradeInfoGSBDto> buildUnsyncTradeInfo(@NotNull String date) {
        //找出所有配置
        List<TOaFlowXirTradeConfigDto> allConfig = xirTradeService.queryAllConfig(
                TOaFlowXirTradeConfigSearchParamDto.builder()
                        .date(date)
                        .workflowTypeList(List.of(XirTradeOaFlowTypeEnum.固定收益部_固定收益部自有资金划拨流程.getCode()))
                        .build());
        if (CollectionUtil.isEmpty(allConfig)) {
            throw new OaflowException("当前无生效配置");
        }
        List<TOaFlowXirTradeInfoGSBDto> res = allConfig.stream()
                .map(config -> {
                    try {
                        衡泰业务类型枚举_固收部 bizType = 衡泰业务类型枚举_固收部.seek(config.getXirBizType());
                        if (!FORMULA_MAP.containsKey(bizType)) {
                            logger.error("XirTradeFactoryGSB生产告警，未找到配方{}，无法生产", bizType.getCode());
                            return null;
                        }
                        //定义上下文
                        BuildContext context = BuildContext.builder()
                                .date(date)
                                .config(config)
                                .bizType(bizType)
                                .build();

                        logger.info("XirTradeFactoryGSB查找账户，配方{}", bizType.getCode());
                        super.initAccid(context);
                        logger.info("XirTradeFactoryGSB查找账户，配方{}, res: cashList:{}, secuList:{}", bizType.getCode(), context.getCashAccidList(), context.getSecuAccidList());
                        if (CollectionUtil.isEmpty(context.getCashAccidList()) && CollectionUtil.isEmpty(context.getSecuAccidList())) {
                            logger.error("XirTradeFactoryGSB生产告警，配方{}无配置的资金/证券账户，无法生产", bizType.getCode());
                            return null;
                        }

                        //根据业务类别拿到具体配方，根据步骤生产
                        for (Function<BuildContext, Boolean> step : FORMULA_MAP.get(bizType)) {
                            if (!step.apply(context)) {
                                break;
                            }
                        }
                        ;
                        return context.getRes();
                    } catch (Exception exception) {
                        logger.error("XirTradeFactory生产异常", exception);
                        return null;
                    }
                })
                .filter(CollectionUtil::isNotEmpty)
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
        return res;
    }

    /**
     * 从trade表查找数据
     */
    private static boolean buildTrade(BuildContext context) {
        logger.info("XirTradeFactoryGSB查找trade-{}", context.getBizType().getCode());
        if (CollectionUtil.isNotEmpty(context.getIntordIdList())) {
            context.setTradeList(otcTradeRepo.findAllByIntordidIn(context.getIntordIdList()));
        } else {
            context.setTradeList(otcTradeRepo.findAllByTrdtypeAndOrddateAndCashAccidInAndSecuAccidInAndOrdstatusInAndIntordidIn(
                    context.getBizType().getCode(), context.getDate(), context.getCashAccidList(), context.getSecuAccidList(),
                    List.of(XirTtrdOtcTradeOrdStatusEnum.审批通过.getCode(), XirTtrdOtcTradeOrdStatusEnum.成交确认.getCode()), context.getIntordIdList()));
        }
        if (CollectionUtil.isEmpty(context.getTradeList())) {
            logger.error("XirTradeFactoryGSB生产告警，配方{}无trade记录，无法生产", context.getBizType().getDesc());
            return false;
        }
        context.setIntordIdList(context.getTradeList().stream().map(TtrdOtcTrade::getIntordid).collect(Collectors.toList()));
        logger.info("XirTradeFactoryGSB查找trade-{}, res:{}", context.getBizType().getCode(), context.getTradeList());
        return true;
    }

    private static boolean buildAndFilterTbnd(BuildContext context) {
        logger.info("XirTradeFactoryGSB查找buildAndFilterTbnd-{}", context.getBizType().getCode());
        List<Tbnd> tbndList = null;
        switch (context.getBizType()) {
            case 债券认购_分销买入_首期:
                //债券交易视图
                List<VtrdOtcTradeAll> vtrdOtcTradeAllList = vtrdOtcTradeAllRepo.findAllByIntordidIn(context.getIntordIdList());
                if (CollectionUtil.isEmpty(vtrdOtcTradeAllList)) {
                    logger.error("XirTradeFactoryGSB生产告警，配方{}无同业存单认购信息，无法生产", context.getBizType().getDesc());
                    return false;
                }
                //金融标的列表，只同步标的为【同业存单】债券的数据
                tbndList = tbndRepo.findAllByPClassInAndICodeIn(vtrdOtcTradeAllList.stream().map(VtrdOtcTradeAll::getUICode).collect(Collectors.toList()), List.of("同业存单"));
                if (CollectionUtil.isEmpty(tbndList)) {
                    logger.error("XirTradeFactoryGSB生产告警，配方{}无同业存单，无法生产", context.getBizType().getDesc());
                    return false;
                }
                context.setTbndList(tbndList);
                Map<String, List<Tbnd>> tbndMap = tbndList.stream().collect(Collectors.groupingBy(Tbnd::getICode));
                context.setTrade2TbndMap(vtrdOtcTradeAllList.stream()
                        .map(o -> new Pair<>(o.getIntordid(),
                                tbndMap.get(o.getUICode()).stream()
                                        .filter(t -> t.getAType().equals(o.getUAType()) && t.getMType().equals(o.getUMType()))
                                        .findAny().orElse(null)
                        ))
                        .filter(p -> Objects.nonNull(p.getValue()))
                        .collect(Collectors.toMap(Pair::getKey, Pair::getValue)));
                //过滤非【同业存单】债券的数据
                context.setTradeList(context.getTradeList().stream().filter(t -> context.getTrade2TbndMap().containsKey(t.getIntordid())).collect(Collectors.toList()));
                context.setIntordIdList(new ArrayList<>(context.getTrade2TbndMap().keySet()));
                return true;
            case 债券借贷_定期付息:
            case 债券借贷_到期:
                if (CollectionUtil.isEmpty(context.getIntordIdList())) {
                    logger.error("XirTradeFactoryGSB生产告警，配方{}无trade信息，无法生产", context.getBizType().getDesc());
                    return false;
                }
                //把trade相关所有inst查出来
                List<TtrdSetInstruction> allInstList = instructionRepo.findAllByIntordidIn(context.getIntordIdList());
                if (CollectionUtil.isEmpty(allInstList)) {
                    logger.error("XirTradeFactoryGSB生产告警，配方{}无inst信息，无法生产", context.getBizType().getDesc());
                    return false;
                }
                List<TtrdSetInstructionSecu> secuList = instructionSecuRepo.findAllByInstIdInAndBiztypeIn(allInstList.stream()
                        .map(TtrdSetInstruction::getInstId)
                        .distinct()
                        .collect(Collectors.toList()), List.of("UNFREEZE",
                        衡泰业务类型枚举_固收部.债券借贷_定期付息.equals(context.getBizType()) ? "RECEIVE" : "MAR_OUT"));
                //找出所有借入券和质押券
                List<String> tbndCodeList = secuList.stream().map(TtrdSetInstructionSecu::getICode).collect(Collectors.toList());
                tbndList = tbndRepo.findAllByICodeIn(tbndCodeList);
                Map<String, List<Tbnd>> tbnd2Market = tbndList.stream().collect(Collectors.groupingBy(Tbnd::getICode));
                //找出需要触发的instruction数据
                Map<String, String> inst2IntordidMap = allInstList.stream().collect(Collectors.toMap(TtrdSetInstruction::getInstId, TtrdSetInstruction::getIntordid));
                Map<String, TtrdSetInstructionSecu> matchSecuMap = secuList.stream().collect(Collectors.groupingBy(secu -> inst2IntordidMap.get(secu.getInstId())))
                        .entrySet().stream()
                        .map(entry -> {
                            List<TtrdSetInstructionSecu> secus = entry.getValue();
                            AtomicReference<TtrdSetInstructionSecu> inMarket = new AtomicReference<>();
                            Set<String> freezMarket = secus.stream()
                                    .map(c -> {
                                        if ((衡泰业务类型枚举_固收部.债券借贷_定期付息.equals(context.getBizType()) ? "RECEIVE" : "MAR_OUT").equals(c.getBiztype())) {
                                            inMarket.set(c);
                                            return null;
                                        } else {
                                            return tbnd2Market.get(c.getICode()).stream()
                                                    .filter(tbnd -> tbnd.getAType().equals(c.getAType()) && tbnd.getMType().equals(c.getMType()))
                                                    .findFirst()
                                                    .map(Tbnd::getHostMarket).orElse(Strings.EMPTY);
                                        }
                                    })
                                    .filter(Strings::isNotBlank)
                                    .collect(Collectors.toSet());
                            if (Objects.isNull(inMarket.get())) {
                                logger.info("固收部债券借贷流程同步{},未找到借入债券instId:{}", context.getBizType().getCode(), entry.getKey());
                                return null;
                            }
                            logger.info("固收部债券借贷流程同步{}, tbnd2Market:{}, inMarket:{}, freezmark{}, instId:{}", context.getBizType().getCode(),
                                    tbnd2Market.entrySet().stream()
                                            .map(ml -> ml.getValue().stream().map(m -> "icode:" + m.getICode() + ",atype:" + m.getAType() + ",mtype:" + m.getMType())
                                                    .collect(Collectors.joining(",")))
                                            .collect(Collectors.joining(",")),
                                    inMarket, freezMarket, entry.getKey());
                            String inmarket = tbnd2Market.get(inMarket.get().getICode()).stream()
                                    .filter(tbnd -> tbnd.getAType().equals(inMarket.get().getAType()) && tbnd.getMType().equals(inMarket.get().getMType()))
                                    .findFirst()
                                    .map(Tbnd::getHostMarket).orElse(Strings.EMPTY);
                            //如果借入券和质押券均为中债或者上清，则无需划款，当存在以下一种时触发：
                            // 1、借入券和质押券的托管市场不一致
                            // 2、借入券和质押券的托管场所均为上交所
                            logger.info("固收部债券借贷流程同步{}, inmark:{}, freezmark{}, instId:{}", context.getBizType().getCode(), inmarket, freezMarket, entry.getKey());
                            return (freezMarket.size() > 1
                                    || !freezMarket.contains(inmarket)
                                    || ("XSHG".equals(inmarket) && freezMarket.contains("XSHG"))
                            ) ? inMarket.get() : null;
                        })
                        .filter(Objects::nonNull)
                        .collect(Collectors.toMap(TtrdSetInstructionSecu::getInstId, s -> s));
                context.setInst2SecuMap(matchSecuMap);
                //筛选符合条件的付息instruction
                context.setInstructionList(context.getInstructionList().stream()
                        .filter(inst -> matchSecuMap.containsKey(inst.getInstId()))
                        .collect(Collectors.toList()));
                context.setTrade2InstMap(context.getInstructionList().stream()
                        .collect(Collectors.toMap(TtrdSetInstruction::getIntordid, o -> o)));
                //筛选trade
                Set<String> intordSet = context.getInstructionList().stream()
                        .map(TtrdSetInstruction::getIntordid)
                        .collect(Collectors.toSet());
                context.setIntordIdList(new ArrayList<>(intordSet));
                context.setTradeList(context.getTradeList().stream()
                        .filter(trade -> intordSet.contains(trade.getIntordid()))
                        .collect(Collectors.toList()));
                logger.info("XirTradeFactoryGSB查找buildAndFilterTbnd-{}, res: inst2SecuMap:{}", context.getBizType().getCode(), context.getInst2SecuMap());
                return true;
            default:
                logger.error("XirTradeFactoryGSB生产告警，配方{}未匹配到业务类型，无法生产", context.getBizType().getDesc());
                return false;
        }
    }

    /**
     * 从指令表查找数据
     */
    private static boolean buildInst(BuildContext context) {
        logger.info("XirTradeFactoryGSB查找inst-{}", context.getBizType().getCode());
        context.setInstructionList(instructionRepo.findAllByBiztypeAndSetdateAndCashAccidInAndSecuAccidIn(
                context.getBizType().getCode(), context.getDate(), context.getCashAccidList(), context.getSecuAccidList()));
        context.setIntordIdList(CollectionUtil.isEmpty(context.getInstructionList()) ? new ArrayList<>(0) :
                context.getInstructionList().stream().map(TtrdSetInstruction::getIntordid).distinct().collect(Collectors.toList()));
        logger.info("XirTradeFactoryGSB查找inst-{}, res:{}", context.getBizType().getCode(), context.getInstructionList());
        return CollectionUtil.isNotEmpty(context.getInstructionList());
    }


    private static boolean buildSecu(BuildContext context) {
        logger.info("XirTradeFactoryGSB查找secu-{}", context.getBizType().getCode());
        if (CollectionUtils.isEmpty(context.getIntordIdList())) {
            logger.error("XirTradeFactoryGSB查找Secu失败，intordid为空");
            return false;
        }
        context.setInst2SecuMap(instructionSecuRepo.findAllByICodeIn(context.getIntordIdList()).stream().collect(Collectors.toMap(TtrdSetInstructionSecu::getInstId, s -> s)));
        logger.info("XirTradeFactoryGSB查找secu-{}, res:{}", context.getBizType().getCode(), context.getInst2SecuMap());
        return CollectionUtil.isNotEmpty(context.getInst2SecuMap());
    }

    /**
     * 过滤掉已经同步过的
     */
    private static boolean fiterSynced(BuildContext context) {
        logger.info("XirTradeFactoryGSB查找fiterSynced-{}", context.getBizType().getCode());
        //找所有存在的记录
        List<TOaFlowXirTradeInfo> existTradeInfoList = xirTradeInfoRepo.findAllByInstIdInAndXirBizTypeAndIntordidIn(null, context.getBizType().getCode(), context.getIntordIdList());
        if (CollectionUtil.isNotEmpty(existTradeInfoList)) {
            context.setExistTradeInfoList(existTradeInfoList);
            if (CollectionUtil.isNotEmpty(context.getTradeList())) {
                //否则直接过滤交易表
                Map<String, String> existIntordIdMap = existTradeInfoList.stream().collect(Collectors.toMap(TOaFlowXirTradeInfo::getIntordid, TOaFlowXirTradeInfo::getDealStatus));
                context.setTradeList(
                        context.getTradeList().stream()
                                .filter(t -> !existIntordIdMap.containsKey(t.getIntordid()) || OaFlowXirTradeInfoStatusEnum.canSync(existIntordIdMap.get(t.getIntordid())))
                                .collect(Collectors.toList())
                );
                context.setIntordIdList(
                        context.getTradeList().stream()
                                .map(TtrdOtcTrade::getIntordid)
                                .collect(Collectors.toList())
                );
            }
        }

        logger.info("XirTradeFactoryGSB查找fiterSynced-{}, res{}", context.getBizType().getCode(), context.getTradeList());
        return true;
    }

    /**
     * 查找对手信息
     */
    private static boolean buildParty(BuildContext context) {
        logger.info("XirTradeFactoryGSB查找party-{}", context.getBizType().getCode());
        if (CollectionUtil.isNotEmpty(context.getTradeList())) {
            List<String> partyIdList = context.getTradeList().stream().map(TtrdOtcTrade::getPartyid).collect(Collectors.toList());
            context.setPartyList(counterpartyBankRepo.findAllByPartyidIn(partyIdList));
        }
        logger.info("XirTradeFactoryGSB查找party-{}, res:{}", context.getBizType().getCode(), context.getPartyList());
        return true;
    }

    /**
     * 组装，虽然对各业务兼容，但仍然需要业务顺序分别进行组装
     */
    private static boolean fit(BuildContext context) {
        if (CollectionUtil.isEmpty(context.getTradeList())) {
            logger.error("XirTradeFactoryGSB生产告警，无可生产列表，type-{}", context.getBizType().getCode());
            return false;
        } else {
            logger.info("XirTradeFactoryGSB开始生产fit, type{}", context.getBizType().getCode());
            //对手银行账户信息
            Map<String, List<TtrdOtcCounterpartyBank>> partyMap = context.getPartyList().stream().filter(b -> Strings.isNotBlank(b.getBankacccode())).collect(Collectors.groupingBy(TtrdOtcCounterpartyBank::getBankacccode));
            //已同步过的
            Map<String, TOaFlowXirTradeInfo> existTradeInfoMap = context.getExistTradeInfoList().stream().collect(Collectors.toMap(TOaFlowXirTradeInfo::getIntordid, o -> o, (o1, o2) -> o1));
            //交易员预查
            setEmpByTraderList(context);
            context.setRes(
                    context.getTradeList().stream()
                            .map(trade -> {
                                //交易对手
                                Optional<TtrdOtcCounterpartyBank> party = Strings.isBlank(trade.getPartyBankAccCode()) ? Optional.empty() :
                                        partyMap.get(trade.getPartyBankAccCode()).stream().filter(b -> b.getAccname().equals(trade.getPartyAccName())).findFirst();
                                TOaFlowXirTradeInfoGSBDto build = TOaFlowXirTradeInfoGSBDto.builder()
                                        .id(existTradeInfoMap.containsKey(trade.getIntordid()) ? existTradeInfoMap.get(trade.getIntordid()).getId() : null)
                                        .dealStatus(OaFlowXirTradeInfoStatusEnum.UNSYNC.getCode())
                                        .workflowId(context.getConfig().getWorkflowId())
                                        .intordid(trade.getIntordid())
                                        .sysordid(trade.getSysordid())
                                        .xirBizType(context.getBizType().getCode())
                                        .xirBizTypeName(trade.getIName())
                                        .cashAccid(trade.getCashAccid())
                                        .secuAccid(trade.getSecuAccid())
                                        .partyId(trade.getPartyid())
                                        .settleFeeDesc(trade.getIName())
                                        .partyName(party.map(TtrdOtcCounterpartyBank::getAccname).orElse(null))
                                        .partyBankCode(trade.getPartyBankCode())
                                        .partyBankAccName(trade.getPartyBankAccName())
                                        .partyAccCode(trade.getPartyBankAccCode())
                                        .partyAccName(trade.getPartyAccName())
                                        //摘要
                                        .bizBrief(trade.getRemark())
                                        //标题
                                        .title(context.getBizType().getTitle())
                                        .dealer(trade.getTrader())
                                        //TODO:允许配置多个人员
                                        //发起人如果未配置，取衡泰发起人
                                        .applicant(getOaUserAccount(context.getConfig(), trade, context.getOaAccountSet()))
                                        .expectDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                                        //保存到草稿
                                        .isnextflow("1")
                                        .detailList(Collections.singletonList(
                                                TOaFlowXirTradeInfoGSBDto.TOaFlowXirTradeInfoDetailGSBDto.builder()
                                                        .paymentDate(context.getBizType().getPayDate(context, trade))
                                                        .payAmount(context.getBizType().getPayAmount(context, trade))
                                                        //付款方信息，已在字段映射表配置默认字段，此处可以为空
//                                                        .paymentOrganization(paymentOrganization)
//                                                        .paymentAccount(paymentAccount)
//                                                        .paymentAccount2(paymentAccount2)
//                                                        .paymentAccountName(paymentAccountName)
//                                                        .paymentAccountBankType(paymentAccountBankType)
//                                                        .paymentAccountBankName(paymentAccountBankName)
//                                                        .paymentLargeAmountAccount(paymentLargeAmountAccount)

                                                        .receiveAccountNameManual(trade.getPartyAccName())
                                                        .receiveAccountManual(trade.getPartyBankAccCode())
                                                        .receiveAccountBankManual(trade.getPartyBankAccName())
                                                        .receiveAccountBankTypeManual(trade.getPartyAccName())
                                                        .receiveLargeAmountAccountManual(party.map(TtrdOtcCounterpartyBank::getBanklargepaynumber).orElse(null))
                                                        .remark(context.getBizType().getRemark(context, context.getTrade2TbndMap().get(trade.getICode()), trade))
                                                        .build()
                                        ))
                                        .build();
                                build.setSyncTime(LocalDateTime.now());
                                build.setDeptTitle(getDeptTitle(build.getApplicant()));
                                return build;
                            })
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList())
            );
            logger.info("XirTradeGSBFactory结束fit, type-{}, res:{}", context.getBizType().getCode(), context.getRes());
            return true;
        }
    }

    /**
     * 生产过程上下文
     */
    @SuperBuilder
    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    @EqualsAndHashCode(callSuper = true)
    public static class BuildContext extends AbstractBuildContext<TOaFlowXirTradeInfoGSBDto> {
        @NotNull
        private 衡泰业务类型枚举_固收部 bizType;

        /**
         * 订单序号列表
         */
        @Nullable
        private List<String> intordIdList;
        /**
         * 指令列表（主要，只有同业拆入到期使用）
         */
        @Builder.Default
        private List<TtrdSetInstruction> instructionList = new ArrayList<>(0);
        @Builder.Default
        private Map<String, TtrdSetInstruction> trade2InstMap = new HashMap<>(0);
        @Builder.Default
        private Map<String, TtrdSetInstructionSecu> inst2SecuMap = new HashMap<>(0);
        @Nullable
        private List<String> tbndCodeList;
        /**
         * 标的工具
         */
        @Builder.Default
        private List<Tbnd> tbndList = new ArrayList<>(0);
//        @Builder.Default
//        private Map<String, Tbnd> tbndMap = new HashMap<>(0);
        /**
         * 标的工具map<tradeId,标的工具>
         */
        @Builder.Default
        private Map<String, Tbnd> trade2TbndMap = new HashMap<>(0);
        /**
         * 对手列表（可能有重复，还需要根据名称再筛查一下）
         */
        @Builder.Default
        private List<TtrdOtcCounterpartyBank> partyList = new ArrayList<>(0);
    }

    @Resource
    public void setOtcTradeRepo(TtrdOtcTradeRepository otcTradeRepo) {
        XirTradeGSBFactory.otcTradeRepo = otcTradeRepo;
    }

    @Resource
    public void setTbndRepo(TbndRepository tbndRepo) {
        XirTradeGSBFactory.tbndRepo = tbndRepo;
    }

    @Resource
    public void setXirTradeInfoRepo(TOaFlowXirTradeInfoRepository xirTradeInfoRepo) {
        XirTradeGSBFactory.xirTradeInfoRepo = xirTradeInfoRepo;
    }

    @Resource
    public void setCounterpartyBankRepo(TtrdOtcCounterpartyBankRepository counterpartyBankRepo) {
        XirTradeGSBFactory.counterpartyBankRepo = counterpartyBankRepo;
    }

    @Resource
    public void setXirTradeService(TOaFlowXirTradeService xirTradeService) {
        XirTradeGSBFactory.xirTradeService = xirTradeService;
    }

    @Resource
    public void setInstructionRepo(TtrdSetInstructionRepository instructionRepo) {
        XirTradeGSBFactory.instructionRepo = instructionRepo;
    }

    @Resource
    public void setVtrdOtcTradeAllRepo(VtrdOtcTradeAllRepository vtrdOtcTradeAllRepo) {
        XirTradeGSBFactory.vtrdOtcTradeAllRepo = vtrdOtcTradeAllRepo;
    }

    @Resource
    public void setInstructionCashRepo(TtrdSetInstructionSecuRepository instructionSecuRepo) {
        XirTradeGSBFactory.instructionSecuRepo = instructionSecuRepo;
    }
}
